home *** CD-ROM | disk | FTP | other *** search
- #!/bin/python
- # -*- coding: iso-8859-1 -*-
-
- """
- ToolPublishBlogroll.py
-
- David Janes
- BlogMatrix
- 2004.02.15
- """
-
- import sys
- import urllib
- import Tool
- import cStringIO
-
- templates = {
- "blogroll" : """\
- <div class="blogroll">
- #for $category in $categories
- <div class="sidetitle">$category</div>
- <div class="side">
- #for $blog in $blogs
- #if $blog.category == $category
- <a href="$escape_html($blog.url)">$escape_html($blog.title)</a>
- <br/>
- #end if
- #end for
- </div>
- #end for
- </div>
- """,
- "opml" : """\
- <?xml version="1.0" encoding="ISO-8859-1"?>
- <opml version="1.0">
- <head>
- <title>OPML Blogroll</title>
- <ownerName>Generated from BlogMatrix JΣger</ownerName>
- </head>
- <body>
- <outline title="Blogroll">
- #for $category in $categories
- <outline title=$quote_attribute($category)>
- #for $blog in $blogs
- #if $blog.category == $category
- <outline
- title=$quote_attribute($blog.title)
- url=$quote_attribute($blog.url)
- #if $blog.syndication_url
- rssUrl=$quote_attribute($blog.syndication_url)
- #end if
- />
- #end if
- #end for
- </outline>
- #end for
- </outline>
- </body>
- </opml>
- """
- }
-
- class ToolPublishBlogroll(Tool.ToolInterface):
- """
- The interface for your tool. Simply create an instance of this object and Jaeger
- will figure it out.
- """
- def __init__(self):
- Tool.ToolInterface.__init__(self, self.WEBSERVER)
-
- def get_label(self, selected):
- return "Publish Blogroll"
-
- def get_server(self, path):
- """
- """
- return {
- "/": ( self.serve_root, "" ),
- "/htmlftp": ( self.serve_htmlftp, "Publish as HTML to an FTP location" ),
- "/opmlftp": ( self.serve_opmlftp, "Publish as OPML to an FTP location" ),
- }.get(path)
-
- def serve_root(self, operations, path, valuemap):
- result = [
- self.text_standard_header(path),
- """
- <h2>Publish Blogroll</h2>
- <p class="first">
- This extension lets you publish your blogroll (i.e. all the weblogs you
- are following) to several well known-blogging tools.
-
- <ul>
- <li>
- <a href="htmlftp">Publish as HTML to an FTP location</a>
- (use this for MovableType)
-
- <li>
- <a href="opmlftp">Publish as OPML to an FTP location</a>
-
- <li>
- <i>More coming...</i>
- <!--
- <li>
- <a href="blogger">Publish to Blogger</a>
-
- <li>
- <a href="blogrolling">Publish to Blogrolling.com</a>
- -->
- </ul>
- """,
- self.text_standard_footer()
- ]
- return 200, "text/html", None, result
-
- def serve_htmlftp(self, operations, path, valuemap):
- return self.serve_underlying(operations, path, valuemap,
- template_key = "blogroll",
- page_title = "Publish as HTML to an FTP server"
- )
-
- def serve_opmlftp(self, operations, path, valuemap):
- return self.serve_underlying(operations, path, valuemap,
- template_key = "opml",
- page_title = "Publish as OPML to an FTP server"
- )
-
- def serve_underlying(self, operations, path, valuemap, template_key, page_title):
- is_form = valuemap.get("_form")
-
- #
- # The 'name' and 'phone' values are persisted through the '*userdata' functions
- #
- hostname = valuemap.get("hostname")
- if hostname == None:
- hostname = operations.get_userdata("hostname_" + template_key, "")
- else:
- operations.set_userdata("hostname_" + template_key, hostname)
-
- username = valuemap.get("username")
- if username == None:
- username = operations.get_userdata("username_" + template_key, "")
- else:
- operations.set_userdata("username_" + template_key, username)
-
- password = valuemap.get("password")
- if password == None:
- password = operations.get_userdata("password_" + template_key, "")
- else:
- operations.set_userdata("password_" + template_key, password)
-
- file = valuemap.get("file")
- if file == None:
- file = operations.get_userdata("file_" + template_key, "")
- else:
- operations.set_userdata("file_" + template_key, file)
-
- startblogroll = valuemap.get("startblogroll")
- if startblogroll == None:
- startblogroll = operations.get_userdata("startblogroll_" + template_key, "<!-- START-BLOGROLL -->")
- else:
- operations.set_userdata("startblogroll_" + template_key, startblogroll)
-
- endblogroll = valuemap.get("endblogroll")
- if endblogroll == None:
- endblogroll = operations.get_userdata("endblogroll_" + template_key, "<!-- END-BLOGROLL -->")
- else:
- operations.set_userdata("endblogroll_" + template_key, endblogroll)
-
- submit = valuemap.get("submit")
-
- template = valuemap.get("template")
- # print "template", template, dir(valuemap)
- if not is_form:
- template = operations.get_userdata("template_" + template_key, "")
- else:
- operations.set_userdata("template_" + template_key, template)
-
- delimeters = valuemap.get("delimeters", "")
- if not is_form:
- delimeters = operations.get_userdata("delimeters_" + template_key, "on")
- else:
- operations.set_userdata("delimeters_" + template_key, delimeters)
-
- # print "serve_htmlftp: B"
- if not template: template = templates.get(template_key, "")
-
- # print "serve_htmlftp: C"
- result = [
- self.text_standard_header(path),
- """<h2>%s</h2>""" % page_title
- ]
-
- # print "serve_htmlftp: D"
- template_result = ""
- if True or submit in [ "Display Here", "Publish", "Publish Blogroll" ]:
- try:
- from Cheetah.Template import Template
-
- t = Template(template)
-
- #
- # blogs are sorted by category, then by title
- #
- t.blogs = operations.get_weblogs()
- t.blogs.sort(lambda a, b: \
- cmp(a["category"].lower(), b["category"].lower()) or \
- cmp(a["title"].lower(), b["title"].lower()))
-
- #
- # we have to derive a list of the category names
- #
- t.categories = {}.fromkeys(map(lambda b : b["category"], t.blogs), 1).keys()
- t.categories.sort()
-
- #
- # some useful functions for the template user
- #
- t.escape_html = self.escape_html
- t.quote_attribute = self.quote_attribute
-
- #
- # generate the result
- #
- template_result = str(t)
- except:
- traceback.print_exc(file = sys.stdout, limit = 2)
-
- # print >> sys.stderr, "A", submit
- if submit == "Publish Blogroll":
- print >> sys.stderr, "ToolPublishBlogroll: called"
- ftp = None
- try:
- if not hostname: raise "'Hostname' is required"
- if not username: raise "'Username' is required"
- if not file: raise "'File' is required"
- if not startblogroll: raise "'Start Blogroll' is required"
- if not endblogroll: raise "'End Blogroll' is required"
-
- import ftplib
-
- ftp = ftplib.FTP()
- print >> sys.stderr, "ToolPublishBlogroll: connecting..."
- ftp.connect(hostname)
-
- print >> sys.stderr, "ToolPublishBlogroll: logging in..."
- ftp.login(username, password)
-
- if not delimeters:
- to_upload = template_result
- else:
- print >> sys.stderr, "Getting current version of the file..."
- try:
- current_file = []
- def callback(block): current_file.append(block)
-
- ftp.retrbinary("RETR %s" % file, callback)
- current_file = "".join(current_file)
- except:
- traceback.print_exc(file = sys.stdout, limit = 2)
- to_upload = "\n".join([ startblogroll, template_result, endblogroll ])
-
- if current_file:
- startx = current_file.find(startblogroll + "\n")
- if startx == -1: raise "Could not find 'Start Blogroll'"
-
- endx = current_file.find(endblogroll, startx + 1)
- if endx == -1: raise "Could not find 'End Blogroll'"
-
- to_upload = \
- current_file[:startx] + \
- startblogroll + "\n" + \
- template_result + \
- current_file[endx:]
-
- sin = cStringIO.StringIO(to_upload)
- print >> sys.stderr, "ToolPublishBlogroll: uploading..."
- ftp.storbinary("STOR %s" % file, sin)
-
- print >> sys.stderr, "ToolPublishBlogroll: closing..."
- ftp.quit()
-
- result.append("""\
- <h3>OK</h3>
- <p class="first">
- The blogroll file was uploaded sucessfully.
- """)
- except:
- try:
- if ftp: ftp.quit()
- except: pass
-
- traceback.print_exc(file = sys.stdout, limit = 2)
- result.append("""\
- <h3>An error occured</h3>
- <p class="first">
- """ + self.escape_html(traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1])[0]))
-
- result.append("""\
- <form method="POST">
- <h3>Login Information</h3>
- <p class="first">
- <table>
-
- <tr>
- <td align="left" width=120>Host:</td>
- <td> </td>
- <td><input type="text" name="hostname" value=\"""" + self.escape_html(hostname) + """"></td>
- </tr>
-
- <tr>
- <td align="left">User:</td>
- <td></td>
- <td><input type="text" name="username" value=\"""" + self.escape_html(username) + """"></td>
- </tr>
-
- <tr>
- <td align="left">Password:</td>
- <td></td>
- <td><input type="password" name="password" value=\"""" + self.escape_html(password) + """"></td>
- </tr>
-
- <tr>
- <td align="left">File:</td>
- <td></td>
- <td><input type="text" name="file" value=\"""" + self.escape_html(file) + """"></td>
- </tr>
-
- <tr>
- <td></td>
- <td></td>
- <td><input type="Submit" name="submit" value="Publish Blogroll"></td>
- </tr>
- </table>
- """)
-
- result.append("""\
- <h3>Template</h3>
- <h4>Delimeters</h4>
- <p class="first">
- When publishing to a file and "Use Delimeters" is set, the strings "Start Blogroll" and
- "End Blogroll" must be found in the file. All the text between these two markers
- will be replaced with the blogroll.
- If Use Delimeters isn't set, the file will be overwritten.
-
- <p>
- <table>
- <tr>
- <td align="left" width=120>Start Blogroll:</td>
- <td> </td>
- <td><input type="text" size=60 name="startblogroll" value=\"""" + self.escape_html(startblogroll) + """"></td>
- </tr>
-
- <tr>
- <td align="left">End Blogroll:</td>
- <td></td>
- <td><input type="text" size=60 name="endblogroll" value=\"""" + self.escape_html(endblogroll) + """"></td>
- </tr>
-
- <tr>
- <td align="left">Use Delimeters:</td>
- <td></td>
- <td><input type="checkbox" name="delimeters" """ + ( delimeters and "checked" or "" ) + """></td>
- </tr>
-
- </table>
-
- <h4>Template</h4>
- <p class="first">
- The template language is <a href="http://www.cheetahtemplate.org/">Cheetah</a>.
- Documentation to follow on the <a href="http://jaeger.blogmatrix.com">blog</a>.
-
- <p>
- <table>
- <tr>
- <td align="left" valign=top width=120>Template:</td>
- <td></td>
- <td><textarea rows=24 cols=50 name="template">""" + self.escape_html(template) + """</textarea></td>
- </tr>
-
- <tr>
- <td></td>
- <td></td>
- <td>
- <input type="Submit" name="submit" value="Save all values">
- <!-- <input type="Submit" name="submit" value="Display Here"> -->
- </td>
- </tr>
- </table>
- </form>
- """)
-
- if True or submit == "Display Here":
- result.append("""\
- <h3>Blogroll</h3>
- <pre class="first" style="background: #CCCCCC">""" + self.escape_html(template_result) + """</pre>""")
-
- result.append(self.text_standard_footer())
- return 200, "text/html", None, result
-
- def serve_cgi(self, operations, path, valuemap):
- result = [
- self.text_standard_header(path),
- "<h4>Path</h4><p>%s" % path,
- "<h4>Parameters</h4><p>",
- ]
-
- for key, value in valuemap.iteritems():
- result.append("%s: %s<br>" % ( key, value ))
-
- result.append(self.text_standard_footer())
- return 200, "text/html", None, result
-
- #
- # creating it will register it
- #
- ToolPublishBlogroll()
-